package cn.xwt.weidisk.util;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.AnonymousCOSCredentials;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.exception.MultiObjectDeleteException;
import com.qcloud.cos.http.HttpMethodName;
import com.qcloud.cos.model.*;
import com.qcloud.cos.region.Region;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author 薛慰涛
 */
public class CosUtils {
    private static final String SECRET_ID = "";
    private static final String SECRET_KEY = "";
    private static final String REGION = "ap-guangzhou";
    private static final String DISK_BUCKET_NAME = "weidisk";
    private static final String DISK_AVATAR_BUCKET_NAME = "weidisk-avata";
    private static final COSCredentials CRED;
    private static final ClientConfig CLIENT_CONFIG;

    static {
        CRED = new BasicCOSCredentials(SECRET_ID, SECRET_KEY);
        Region region = new Region(REGION);
        CLIENT_CONFIG = new ClientConfig(region);
    }


    /**
     * 获取上传链接
     * @param key 文件名
     * @return String
     */
    public static String getFileUploadUrl(String key) {
        COSClient cosClient = new COSClient(CRED, CLIENT_CONFIG);
        // 这里设置签名在1个小时后过期
        Date expirationTime = new Date(System.currentTimeMillis() + 60L * 60L * 1000L);
        URL url = cosClient.generatePresignedUrl(DISK_BUCKET_NAME, key, expirationTime, HttpMethodName.PUT);
        cosClient.shutdown();
        return url.toString();
    }

    /**
     * 获取下载链接
     * @param key 文件名
     * @return String
     */
    public static String getFileDownloadUrl(String name, String key) throws UnsupportedEncodingException {
        COSClient cosClient = new COSClient(CRED, CLIENT_CONFIG);
        GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(DISK_BUCKET_NAME, key, HttpMethodName.GET);
        // 自定义返回头
        String contentDisposition = "attachment;filename=" + URLEncoder.encode(name, "utf-8");
        ResponseHeaderOverrides responseHeaders = new ResponseHeaderOverrides();
        responseHeaders.setContentDisposition(contentDisposition);
        req.setResponseHeaders(responseHeaders);
        // 定义过期时间
        Date expirationDate = new Date(System.currentTimeMillis() + 60L * 60L * 1000L);
        req.setExpiration(expirationDate);
        URL url = cosClient.generatePresignedUrl(req);
        cosClient.shutdown();
        return url.toString();
    }

    /**
     * 获取预览链接
     * @param key 文件名
     * @return String
     */
    public static String getPreviewUrl(String key) {
        COSClient cosClient = new COSClient(CRED, CLIENT_CONFIG);
        GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(DISK_BUCKET_NAME, key, HttpMethodName.GET);
        // 定义过期时间 30分钟
        Date expirationDate = new Date(System.currentTimeMillis() + 30L * 60L * 1000L);
        req.setExpiration(expirationDate);
        URL url = cosClient.generatePresignedUrl(req);
        cosClient.shutdown();
        return url.toString();
    }

    /**
     * 通过输入流上传缩略图
     * @param inputStream 输入流
     * @param thumbnailKey 缩略图文件名
     * @throws IOException 错误
     */
    public static void uploadThumbnail(InputStream inputStream, String thumbnailKey) throws Exception {
        // 修改缩略图后缀为jpg
        String jpgSuffix = ".jpg";
        String tag = "_thumbnail";
        String uuid = thumbnailKey.substring(0, thumbnailKey.lastIndexOf("."));
        thumbnailKey = uuid + tag + jpgSuffix;
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(inputStream.available());
        objectMetadata.setContentType("image/jpeg");
        COSClient cosClient = new COSClient(CRED, CLIENT_CONFIG);
        cosClient.putObject(DISK_BUCKET_NAME, thumbnailKey, inputStream, objectMetadata);
        cosClient.shutdown();
    }

    /**
     * 删除cos中的文件
     * @param keyList 要删除的键
     */
    public static void deleteObjects(List<String> keyList) {
        COSClient cosClient = new COSClient(CRED, CLIENT_CONFIG);
        DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(DISK_BUCKET_NAME);
        // 设置要删除的key列表, 最多一次删除1000个
        ArrayList<DeleteObjectsRequest.KeyVersion> deleteList = new ArrayList<>();
        // 传入要删除的文件名
        for (String item : keyList) {
            deleteList.add(new DeleteObjectsRequest.KeyVersion(item));
        }
        deleteObjectsRequest.setKeys(deleteList);
        // 批量删除文件
        try {
            DeleteObjectsResult deleteObjectsResult = cosClient.deleteObjects(deleteObjectsRequest);
            List<DeleteObjectsResult.DeletedObject> deleteObjectResultArray = deleteObjectsResult.getDeletedObjects();
        } catch (MultiObjectDeleteException mde) { // 如果部分删除成功部分失败, 返回MultiObjectDeleteException
            List<DeleteObjectsResult.DeletedObject> deleteObjects = mde.getDeletedObjects();
            List<MultiObjectDeleteException.DeleteError> deleteErrors = mde.getErrors();
        } catch (CosServiceException e) { // 如果是其他错误，例如参数错误， 身份验证不过等会抛出 CosServiceException
            e.printStackTrace();
            throw e;
        } catch (CosClientException e) { // 如果是客户端错误，例如连接不上COS
            e.printStackTrace();
            throw e;
        } finally {
            cosClient.shutdown();
        }
    }

    /**
     * 保存头像
     * @param inputStream 输入流
     * @param key 头像名
     * @throws IOException 错误
     */
    public static void uploadAvatar(InputStream inputStream, String key) throws IOException {
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(inputStream.available());
        objectMetadata.setContentType("image/jpeg");
        COSClient cosClient = new COSClient(CRED, CLIENT_CONFIG);
        cosClient.putObject(DISK_AVATAR_BUCKET_NAME, key, inputStream, objectMetadata);
        cosClient.shutdown();
    }

    /**
     * 获取头像链接
     * @param key 头像
     * @return String
     */
    public static String getAvatarLink(String key) {
        COSCredentials cred = new AnonymousCOSCredentials();
        COSClient cosClient = new COSClient(cred, CLIENT_CONFIG);
        GeneratePresignedUrlRequest req =
                new GeneratePresignedUrlRequest(DISK_AVATAR_BUCKET_NAME, key, HttpMethodName.GET);
        URL url = cosClient.generatePresignedUrl(req);
        cosClient.shutdown();
        return url.toString();
    }
}
